/*
* $Id: HousingManager.cpp 302 2011-04-08 15:18:13Z volok-aleksej@yandex.ru $
*
* Copyright 2009-2011 by Volokitin Alexey
* All rights reserved
*
*/
#include "Common/include.h"
#include "HousingManager.h"
#include "Event/EventId.h"
#include "Database/Tables/HousingsTable.h"
#include "Database/Tables/TypesTable.h"
#include "Database/Operation/UpdateFHOperation.h"

#include "RefObject.h"
CRefObject<CHousingManager> g_HousingManager;
CHousingManager* IJournalComponent::GetHousingManager(){
	return g_HousingManager.GetObject();
}

/************************************************************************/
/*                    CHousingManager::housing                          */
/************************************************************************/
CHousingManager::housing::housing()
: m_nIdFamily(0), m_typeframes(0), m_typeHousing(0), m_bDelete(false){}
CHousingManager::housing::housing(const housing& hive){
	operator = (hive);
}
void CHousingManager::housing::operator=(const housing& hive){
	m_nIdFamily = hive.m_nIdFamily;
	m_typeHousing = hive.m_typeHousing;
	m_typeframes = hive.m_typeframes;
	m_strName = hive.m_strName;
	m_bDelete = hive.m_bDelete;
}

/************************************************************************/
/*                        CHousingManager                               */
/************************************************************************/
CHousingManager::CHousingManager(){}
CHousingManager::~CHousingManager(){}

void CHousingManager::Init(){
	IDatabase* pDb = IDatabaseManager::GetDatabaseManager()->OpenDatabase(JOURNAL_DATABASE_NAME);
	CHousingsTable houseTable;
	IResult* pResult = houseTable.GetValue(pDb);
	for(int i = 0; i < (int)pResult->GetSizeResult(); i++){
		CHousingsTable::content* pContent = (CHousingsTable::content*)(*pResult)[i];
		housing hive;
		hive.m_strName = pContent->s_strName;
		hive.m_nIdFamily = pContent->s_nIdFamily;
		hive.m_typeHousing = pContent->s_nType;
		hive.m_typeframes = pContent->s_nFrames;
		hive.m_bDelete = pContent->s_bDelete;
		m_aHousings.insert(std::make_pair(pContent->s_nId, hive));
		m_aFamilyHousing[pContent->s_nIdFamily].push_back(pContent->s_nId);
	}
	pResult->Free();
	CTypeHousingsTable typehTable;
	pResult = typehTable.GetValue(pDb);
	for (size_t i = 0; i < pResult->GetSizeResult(); i++){
		CTypeHousingsTable::content* cnt = (CTypeHousingsTable::content*)(*pResult)[(int)i];
		std::tstring strName;
		if(cnt->s_nId >= 0 && cnt->s_nId < 8 && cnt->s_strName.empty())
			strName = ILanguageManager::GetLanguageManager()->GetString(EIGHT_FRAME_HOUSING_ID + cnt->s_nId);
		else
			strName = cnt->s_strName;
		m_aTypeHousing.insert(std::make_pair(cnt->s_nId, strName));
	}
	pResult->Free();
	CTypeFrameTable typefTable;
	pResult = typefTable.GetValue(pDb);
	for (size_t i = 0; i < pResult->GetSizeResult(); i++){
		CTypeFrameTable::content* cnt = (CTypeFrameTable::content*)(*pResult)[(int)i];
		std::tstring strName;
		if(cnt->s_nId >= 0 && cnt->s_nId < 7 && cnt->s_strName.empty())
			strName = ILanguageManager::GetLanguageManager()->GetString(S300_ID + cnt->s_nId);
		else
			strName = cnt->s_strName;
		m_aTypeFrame.insert(std::make_pair(cnt->s_nId, strName));
	}
	pResult->Free();
	IDatabaseManager::GetDatabaseManager()->CloseDatabase(pDb);
}

std::map<int, CHousingManager::housing> CHousingManager::GetHousings(){
	return m_aHousings;
}

CHousingManager::housing CHousingManager::GetHousing(int nIdHousing){
	return m_aHousings[nIdHousing];
}

void CHousingManager::UpdateHousing(int nId, const housing& hive){
	IDatabase* pDb = IDatabaseManager::GetDatabaseManager()->OpenDatabase(JOURNAL_DATABASE_NAME);
	CHousingsTable table;
	table.m_content.s_strName = hive.m_strName;
	table.m_content.s_nType = hive.m_typeHousing;
	table.m_content.s_nFrames = hive.m_typeframes;
	table.m_content.s_nIdFamily = hive.m_nIdFamily;
	table.m_content.s_bDelete = hive.m_bDelete;
	table.m_content.s_nId = nId;
	table.UpdateValue(pDb);
	m_aHousings[nId] = hive;
	IDatabaseManager::GetDatabaseManager()->CloseDatabase(pDb);
	IEventManager::GetEventManager()->SendEvent(HOUSING_DB_CHANGE_EVENT);
}

int CHousingManager::AddHousing(const housing& hive){
	IDatabase* pDb = IDatabaseManager::GetDatabaseManager()->OpenDatabase(JOURNAL_DATABASE_NAME);
	pDb->BeginTransaction(_T("Add Housing"));
	CHousingsTable table;
	table.m_content.s_strName = hive.m_strName;
	table.m_content.s_nType = hive.m_typeHousing;
	table.m_content.s_nFrames = hive.m_typeframes;
	table.m_content.s_nIdFamily = hive.m_nIdFamily;
	table.m_content.s_bDelete = hive.m_bDelete;
	table.SetValue(pDb);
	m_aHousings[table.m_content.s_nId] = hive;
	m_aFamilyHousing[0].push_back(table.m_content.s_nId);
	pDb->EndTransaction(_T("Add Housing"));
	IDatabaseManager::GetDatabaseManager()->CloseDatabase(pDb);
	return table.m_content.s_nId;
	IEventManager::GetEventManager()->SendEvent(HOUSING_DB_CHANGE_EVENT);
}

void CHousingManager::DeleteHousing(int nId){
	IDatabase* pDb = IDatabaseManager::GetDatabaseManager()->OpenDatabase(JOURNAL_DATABASE_NAME);
	CHousingsTable table;
	table.m_content.s_nId = nId;
	table.DeleteValue(pDb);
	std::vector<int>& families = m_aFamilyHousing[m_aHousings[nId].m_nIdFamily];
	std::vector<int>::iterator it = std::find(families.begin(), families.end(), nId);
	if(it != families.end())
		families.erase(it);
	m_aHousings.erase(nId);
	IDatabaseManager::GetDatabaseManager()->CloseDatabase(pDb);
	IEventManager::GetEventManager()->SendEvent(HOUSING_DB_CHANGE_EVENT);
}

std::map<int, std::tstring> CHousingManager::GetType(Housing::change_type tp){
	if(tp == Housing::HOUSING)
		return m_aTypeHousing;
	else
		return m_aTypeFrame;
}

std::tstring CHousingManager::GetType(Housing::change_type tp, int idType){
	if(tp == Housing::HOUSING)
		return m_aTypeHousing[idType];
	else
		return m_aTypeFrame[idType];
}

void CHousingManager::DeleteType(Housing::change_type tp, int nId){
	IDatabase* pDatabase = IDatabaseManager::GetDatabaseManager()->OpenDatabase(JOURNAL_DATABASE_NAME);
	CTypeTable* pTable;
	std::map<int, std::tstring>* aTypes = NULL;
	if(tp == Housing::HOUSING){
		pTable = new CTypeHousingsTable;
		aTypes = &m_aTypeHousing;
	}else if(tp == Housing::FRAME){
		pTable = new CTypeFrameTable;
		aTypes = &m_aTypeFrame;
	}
	pTable->m_content.s_nId = nId;
	pTable->DeleteValue(pDatabase);
	aTypes->erase(nId);
	delete pTable;
	IDatabaseManager::GetDatabaseManager()->CloseDatabase(pDatabase);
}

int CHousingManager::AddType(Housing::change_type tp, const std::tstring& strType){
	IDatabase* pDatabase = IDatabaseManager::GetDatabaseManager()->OpenDatabase(JOURNAL_DATABASE_NAME);
	CTypeTable* pTable;
	std::map<int, std::tstring>* aTypes = NULL;
	if(tp == Housing::HOUSING){
		pTable = new CTypeHousingsTable;
		aTypes = &m_aTypeHousing;
	}else if(tp == Housing::FRAME){
		pTable = new CTypeFrameTable;
		aTypes = &m_aTypeFrame;
	}
	pTable->m_content.s_strName = strType;
	pTable->SetValue(pDatabase);
	int idType = pTable->m_content.s_nId;
	aTypes->insert(std::make_pair(idType, strType));
	delete pTable;
	IDatabaseManager::GetDatabaseManager()->CloseDatabase(pDatabase);
	return idType;
}

std::map<int, CHousingManager::housing> CHousingManager::GetFamilyHousings(int nIdFamily){
	std::map<int, housing> aHousings;
	for(std::vector<int>::iterator it = m_aFamilyHousing[nIdFamily].begin(); it != m_aFamilyHousing[nIdFamily].end(); it++)
		aHousings.insert(std::make_pair(*it, m_aHousings[*it]));
	return aHousings;
}

void CHousingManager::SetFamily(int nId, int nIdFamily){
	std::vector<int>& aHousing = m_aFamilyHousing[m_aHousings[nId].m_nIdFamily];
	std::vector<int>::iterator it = std::find(aHousing.begin(), aHousing.end(), nId);
	if(it != aHousing.end())
		aHousing.erase(it);
	m_aFamilyHousing[nIdFamily].push_back(nId);
	m_aHousings[nId].m_nIdFamily = nIdFamily;
	IDatabase* pDatabase = IDatabaseManager::GetDatabaseManager()->OpenDatabase(JOURNAL_DATABASE_NAME);
	CUpdateFHOperation operation;
	operation.m_content.s_nId = nId;
	operation.m_content.s_nIdNewFamily = nIdFamily;
	operation.UpdateValue(pDatabase);
	IDatabaseManager::GetDatabaseManager()->CloseDatabase(pDatabase);
	IEventManager::GetEventManager()->SendEvent(HOUSING_DB_CHANGE_EVENT);
}

void CHousingManager::DeleteFamilies(int nIdFamily){
	for(std::vector<int>::iterator it = m_aFamilyHousing[nIdFamily].begin(); it != m_aFamilyHousing[nIdFamily].end(); it++){
		m_aFamilyHousing[0].push_back(*it);
		m_aHousings[*it].m_nIdFamily = 0;
	}
	m_aFamilyHousing.erase(nIdFamily);
	IDatabase* pDatabase = IDatabaseManager::GetDatabaseManager()->OpenDatabase(JOURNAL_DATABASE_NAME);
	CUpdateFHOperation operation;
	operation.m_content.s_nIdFamily = nIdFamily;
	operation.UpdateValue(pDatabase);
	IDatabaseManager::GetDatabaseManager()->CloseDatabase(pDatabase);
}
